home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
amiga
/
viewers
/
ham8_jpg.lha
/
ham8-jpeg
/
Source
/
ham8.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
11KB
|
460 lines
/*
* ham8.c Michael Saunby M.Saunby@reading.ac.uk
*
* Release 1.1 December 1992 A public screen plus utilities to give a pseudo
* 24 bit display on Amigas with AGA graphics (A1200 and A4000).
*
* The AGA HAM-8 mode allows 64 colours to be defined - 48 of these will be
* defined by this program (see display24.c) leaving 8 for intuition and
* client programs.
*/
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <intuition/screens.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/gadtools.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdlib.h>
#include "display24.h"
/*
* If you turn this into something different feel free to change this, but if
* you don't leave it alone!!
*/
#define COPYRIGHT_MESSAGE "Version 1.1\nDecember 1992\n\nCopyright ⌐ 1992\n\
Michael Saunby"
/*
* Template etc for ReadArgs() - Pity it can't read tooltypes
*/
#define TEMPLATE "W=Width/N,H=Height/N,L=LoRes/S"
#define OPT_WIDTH 0
#define OPT_HEIGHT 1
#define OPT_LORES 2
#define OPT_COUNT 3
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct Library *GadToolBase = NULL;
extern struct ExecBase *SysBase;
BOOL restart = FALSE; /* used for resize - see main() */
UWORD width, height;
BOOL lores;
struct Screen *screen;
struct MsgPort *messageport;
ULONG allocsignal;
/*
* Message structure used to get screen size changed, see main()
*/
struct TestMsg
{
struct Message msg;
USHORT Width;
USHORT Height;
BOOL Lores;
};
/*
* Easy Requester used for error messages
*/
struct EasyStruct failedES =
{sizeof (struct EasyStruct), 0, HAM8_ALBERT_NAME,
"%s", "OK",};
/*
* Gadtools menu
*/
#define ABOUT 1
#define QUIT 2
struct NewMenu prj_menu[] =
{
{NM_TITLE, "Project", 0, 0, 0, 0,},
{NM_ITEM, "About...", "?", 0, 0, (void *) ABOUT,},
{NM_ITEM, "Quit", "Q", 0, 0, (void *) QUIT,},
{NM_END, NULL, 0, 0, 0, 0,},
};
/*
* Cleanup() - Close screen and libraries before exit
*/
VOID Cleanup (VOID);
VOID
Cleanup ()
{
if (restart)
{
/*
* Failed to open screen for client. There is a message port waiting
* for a reply.
*/
}
if (screen)
{
CloseScreen (screen);
FreeSignal (allocsignal);
}
if (GadToolBase)
CloseLibrary (GadToolBase);
if (IntuitionBase)
CloseLibrary ((struct Library *) IntuitionBase);
if (GfxBase)
CloseLibrary ((struct Library *) GfxBase);
}
/*
* Quit() - Cleanup and exit on error
*/
VOID Quit ();
VOID
Quit (char whytext[], UBYTE failcode)
{
EasyRequest (NULL, &failedES, NULL, whytext);
Cleanup ();
DeletePort (messageport);
exit (failcode);
}
/*
* CreateScreen() - Main function, build and open a public screen
*/
VOID
CreateScreen ( /* USES GLOBALS width, height, lores, restart */ )
{
ULONG modeID = HIRESHAMLACE_KEY;
DisplayInfoHandle displayhandle;
struct DimensionInfo dimensioninfo;
UWORD maxdepth;
ULONG soerror = NULL;
ULONG signal, wsignal, lastsignal;
ULONG psignal; /* Message port - Another copy of program
* started */
struct Task *task;
BOOL abort = FALSE, closedown = FALSE;
UWORD oldstatus;
struct IntuiMessage *msg;
static struct TestMsg *newdims_msg; /* MUST be static, reply is delayed! */
struct Window *window;
struct Menu *menu;
void *vi;
if (lores)
modeID = HAM_KEY;
if ((GfxBase =
(struct GfxBase *) OpenLibrary ("graphics.library", 36)) == NULL)
Quit ("graphics.library is too old <V36", 25);
if ((IntuitionBase =
(struct IntuitionBase *) OpenLibrary ("intuition.library", 36)) == NULL)
Quit ("intuition.library is too old <V36", 25);
if ((displayhandle = FindDisplayInfo (modeID)) == NULL)
Quit ("modeID not found in display database", 25);
if (GetDisplayInfoData (displayhandle, (UBYTE *) & dimensioninfo,
sizeof (struct DimensionInfo), DTAG_DIMS, NULL) == 0)
Quit ("mode dimension info not available", 25);
/*
* Public screen needs a signal and pointer to this task.
*/
if ((allocsignal = AllocSignal (-1)) == -1)
Quit ("could not allocate signal", 25);
lastsignal = 1 << allocsignal;
task = (struct Task *) & ((struct Process *) FindTask (NULL))->pr_Task;
/*
* MaxDepth will always be 8 for Ham8 mode. But it can't hurt.
*/
maxdepth = dimensioninfo.MaxDepth;
/*
* If you always want a standard size just use SA_Overscan, OSCAN_TEXT
* etc. I have to get the dimensions from dimensioninfo because I always
* set the width and height.
*/
if (width == 0)
width = dimensioninfo.TxtOScan.MaxX - dimensioninfo.TxtOScan.MinX;
if (height == 0)
height = dimensioninfo.TxtOScan.MaxY - dimensioninfo.TxtOScan.MinY;
/*
* Screen is based on workbech to give a familiar look. Could possibly
* cause problems is the default is a 256 colour WB, must try that
* sometime and see what happens.
*/
if ((screen = OpenScreenTags (NULL,
SA_LikeWorkbench, TRUE, /* see above */
SA_Overscan, OSCAN_TEXT,
SA_AutoScroll, TRUE,
SA_DisplayID, modeID,
SA_Depth, (UBYTE) maxdepth,
SA_Width, width,
SA_Height, height,
SA_Title, HAM8_ALBERT_NAME,
SA_PubName, HAM8_ALBERT_NAME,
SA_PubSig, allocsignal,
SA_PubTask, task,
SA_ErrorCode, &soerror,
SA_SharePens, TRUE,
TAG_END)) == NULL)
{
/*
* There are many reasons why this might fail, though on an AGA
* machine only NOCHIPMEM is likely. The other tests are worth
* keeping for when this code is next used.
*/
switch (soerror)
{
case OSERR_NOCHIPS:
Quit ("Amiga custom chips not AGA", 25);
break;
case OSERR_UNKNOWNMODE:
Quit ("Cannot open screen in this mode", 25);
break;
case OSERR_NOCHIPMEM:
Quit ("Not enough CHIP memory", 25);
break;
case OSERR_NOMEM:
Quit ("Not enough memory (CHIP or FAST)", 25);
break;
default:
Quit ("Unspecified error opening screen", 25);
break;
}
}
/*
* StandardPalette() returns number of errors (see display24.c) I ignore
* the errors here and leave it to the client programs to deal with.
*/
(VOID) StandardPalette (&(screen->ViewPort), FALSE);
if ((menu = CreateMenus (prj_menu, GTMN_FrontPen, 1, TAG_DONE)) == NULL)
Quit ("could not build menu", 25);
/*
* Open a backdrop window to which the above menu is attached.
*/
if ((window = OpenWindowTags (NULL,
WA_Top, screen->BarHeight + 1,
WA_Height, screen->Height -
(screen->BarHeight + 1),
WA_CustomScreen, screen,
WA_NewLookMenus, TRUE,
WA_IDCMP, MENUPICK,
WA_Flags, ACTIVATE | BACKDROP | BORDERLESS | NOCAREREFRESH,
TAG_END)) == NULL)
Quit ("could not open backdrop window", 25);
/*
* visual info need to get proper look for menu
*/
vi = GetVisualInfo (screen, TAG_END);
if (LayoutMenus (menu, vi, TAG_DONE) == NULL)
Quit ("could not layout menu", 25);
FreeVisualInfo (vi);
SetMenuStrip (window, menu);
/*
* now go public
*/
oldstatus = PubScreenStatus (screen, 0);
/*
* come forward if and window opens on this screen
*/
SetPubScreenModes (POPPUBSCREEN);
if (restart)
{
ReplyMsg ((struct Message *) newdims_msg);
restart = FALSE;
}
/*
* Now wait until told to quit by user (from menu) waiting of course for
* any visitors to leave.
*/
psignal = 1 << messageport->mp_SigBit;
wsignal = 1 << window->UserPort->mp_SigBit;
do
{
signal = Wait (wsignal | lastsignal | psignal);
if (signal & psignal)
{
newdims_msg = (struct TestMsg *) GetMsg (messageport);
width = newdims_msg->Width;
height = newdims_msg->Height;
lores = newdims_msg->Lores;
restart = TRUE;
/* NB. no reply to message until we have new screen */
if ((oldstatus = PubScreenStatus (screen,
PSNF_PRIVATE)) & 1)
{
abort = TRUE;
}
else
{
closedown = TRUE;
EasyRequest (window, &failedES,
NULL,
"Cannot resize yet, there are other programs");
}
}
if (signal & lastsignal)
{
if (closedown)
if ((oldstatus = PubScreenStatus (screen, PSNF_PRIVATE))
& 1)
abort = TRUE;
}
while (msg = (struct IntuiMessage *) GetMsg (window->UserPort))
{
if (msg->Class == MENUPICK)
{
switch ((UWORD) MENU_USERDATA (ItemAddress (menu, msg->Code)))
{
case ABOUT:
EasyRequest (window, &failedES,
NULL,
COPYRIGHT_MESSAGE);
break;
case QUIT:
if ((oldstatus = PubScreenStatus (screen,
PSNF_PRIVATE)) & 1)
{
abort = TRUE;
}
else
{
closedown = TRUE;
EasyRequest (window, &failedES,
NULL,
"Cannot Quit yet,\nthere are other programs");
}
break;
}
}
ReplyMsg ((struct Message *) msg);
}
} while (abort == FALSE);
/*
* Cleanup part 1. (part 2 is Cleanup())
*/
ClearMenuStrip (window);
CloseWindow (window);
Cleanup ();
}
/*
* If another copy of this program is already running we just tell it what
* size of screen we want then exit.
*/
void
main ()
{
LONG result[OPT_COUNT] =
{0, 0, 0};
struct RDArgs *rda;
BOOL running = FALSE; /* set to true if we find another
* copy running */
struct MsgPort *testport, *progport;
struct TestMsg *msg;
/*
* Default values - 0 means Text overscan size ie Workbench like defaults
*/
width = 0;
height = 0;
lores = FALSE;
rda = ReadArgs (TEMPLATE, result, NULL);
if (result[OPT_WIDTH])
width = *(LONG *) result[OPT_WIDTH];
if (result[OPT_HEIGHT])
height = *(LONG *) result[OPT_HEIGHT];
if (result[OPT_LORES])
lores = TRUE;
FreeArgs (rda);
/*
* Check if copy of program running already
*/
if (testport = CreatePort (NULL, NULL))
{
if (msg = AllocMem (sizeof (struct TestMsg), MEMF_PUBLIC | MEMF_CLEAR))
{
msg->msg.mn_ReplyPort = testport;
msg->msg.mn_Length = sizeof (struct TestMsg);
msg->Width = width;
msg->Height = height;
msg->Lores = lores;
Forbid ();
if (progport = FindPort (HAM8_ALBERT_NAME))
{
PutMsg (progport, (struct Message *) msg);
Permit ();
WaitPort (testport);
msg = (struct TestMsg *) GetMsg (testport);
running = TRUE;
}
Permit ();
FreeMem (msg, (ULONG) sizeof (struct TestMsg));
}
DeletePort (testport);
}
if (running)
return;
messageport = CreatePort (HAM8_ALBERT_NAME, NULL);
/*
* Go around this loop each time the screen is resized. al-backdrop.c
* uses this feature.
*/
do
{
CreateScreen (lores, width, height);
} while (restart);
DeletePort (messageport);
}